# 存放所有的工具函数
# coding:utf-8
import datetime
import math
import os
import random
import re

import pythoncom
from App.utils.ppt2pic import convert_ppt
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from django.core.mail import send_mail
from django.utils.safestring import mark_safe

from App.models import User, OrderManager, Order, AllMessageM, MyMessageM
from Wedding import settings

now_time = datetime.datetime.now().date()
str_now_time = str(now_time)


#
# # session网页登录认证装饰器
# def login_auth(func):
#     def wrapper(request, *args, **kwargs):
#         # 获取目标访问的url路径
#         target_url = request.get_full_path()
#         # 如果session数据符合登录要求，直接跳过登录
#         user_id = request.session.get('userId')
#         # if request.session:    WARN:request.session是一个对象而不是空字典，所以不可直接if。
#         if User.objects.filter(userId=user_id):
#             res = func(request, *args, **kwargs)
#             return res
#         # 若无session数据则跳转至登录界面
#         else:
#             return redirect('/?next={}'.format(target_url))
#
#     return wrapper


# 生成验证码
def check_code(width=120, height=30, char_length=5, font_file='kumo.ttf', font_size=28):
    """
    :param width: 框宽度
    :param height: 框高度
    :param char_length: 字符数量
    :param font_file: 字体样式
    :param font_size: 字体大小
    :return: 图片对象；文字内容
    """
    code = []
    img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    def rndChar():
        """
        :return: 随机字母
        """
        return chr(random.randint(65, 90))

    def rndColor():
        """
        :return: 随机颜色
        """
        return random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)

    # 写文字
    font = ImageFont.truetype(font_file, font_size)
    for i in range(char_length):
        char = rndChar()
        code.append(char)
        h = random.randint(0, 4)
        draw.text((i * width / char_length, h), char, font=font, fill=rndColor())

    # 写干扰点
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    return img, ''.join(code)


# 对注册时用户名是否规范进行判断
def judge_username(username):
    """
    :param username: 用户名
    :return: bool类型
    """
    if username != "" and re.match('^[a-zA-Z0-9]', username):
        return True
    else:
        return False


# 对注册时密码是否规范进行判断
def judge_password(password):
    """
    :param password: 密码
    :return: bool类型
    """
    judge_list = {
        'letter': 0,
        'number': 0,
        'sign': 0,
    }
    for i in password:
        if 65 <= ord(i) <= 90 or 97 <= ord(i) <= 122:
            judge_list['letter'] += 1
        elif 48 <= ord(i) <= 57:
            judge_list['number'] += 1
        else:
            judge_list['sign'] += 1
    if 0 in judge_list.values():
        return False
    else:
        return True


# 判断账户类型
def judge_admin_type(real_admin_type):
    """
    :param real_admin_type: 数据库内实际存入用户权限
    :return: 中文转化
    """
    if real_admin_type == 'administrator':
        return '管理员'
    else:
        return '普通用户'


# 将上传图片命名
def get_new_name(name, img_name):
    """
    :param name: 用户上传图片名
    :param img_name: 图片名称
    :return: 格式化后图片名称
    """
    # file_type + 年月日时秒
    # new_name = time.strftime(name + '-%Y%m%d%H%M%S', time.localtime())
    # 用Python中的numpy库中的random.randint(a,b,n)表示随机生成n个大于等于a小于b的整数
    tmp_str = img_name.split('.')
    new_name = str(name) + '.' + tmp_str[-1]
    return new_name


#  处理上传的图片
def upload_handle(file, img_name, user_id, dir_name):
    """
    :param file: 图片地址
    :param img_name: 图片名称
    :param username: 用户名
    """
    # 保存文件
    new_name = get_new_name(user_id, img_name)
    user = User.objects.filter(userId=user_id)
    # 将要保存的地址和文件名称
    where = '%s/%s/%s' % (settings.MEDIA_ROOT, dir_name, new_name)
    # 分块保存image
    content = file.chunks()
    with open(where, 'wb') as f:
        for i in content:
            f.write(i)
    # 上传文件名称到数据库
    user.update(headImg=dir_name + '/' + new_name)  # 直接存放文件
    return


def upload_mul_handle(images, img_name, dir_name, model):
    """
    :param images: 多图列表
    :param img_name: 多图名称列表
    :param dir_name: 目标目录名称
    :param model: 数据库表名
    """
    point_obj = model.objects.last()
    img_all = ''
    for i in range(len(images)):
        name = point_obj.get_img_id() + '-' + str(i)
        new_name = get_new_name(name, img_name[i])
        where = '%s/%s/%s' % (settings.MEDIA_ROOT, dir_name, new_name)
        # 分块保存image
        content = images[i].chunks()
        with open(where, 'wb') as f:
            for j in content:
                f.write(j)
        img_all += ' ' + new_name
    point_obj.set_my_img(img_all.strip())
    point_obj.save()


# def update_mul_handle(dic, wait_update_id, dir_name, img, model):
#     """
#     :param dic:过滤字典
#     :param wait_update_id: 待更新id
#     :param dir_name: 目标目录名称
#     :param img: 图片地址
#     :param model: 数据库表名
#     :return:
#     """
#     point_obj = model.objects.filter(**dic)
#     images = point_obj.values('img')['img'].split(' ')
#     wait_delete_url = images[wait_update_id - 1]
#     os.remove('%s/%s/%s' % (settings.MEDIA_ROOT, dir_name, wait_delete_url))
#     where = '%s/%s/%s' % (settings.MEDIA_ROOT, dir_name, wait_delete_url)
#     # 分块保存image
#     content = img.chunks()
#     with open(where, 'wb') as f:
#         for j in content:
#             f.write(j)


# 日历简报
def calendar_mask(user_id):
    """
    :param user_id: 用户登录id
    :return: 剩余任务数量；今日需沟通任务数量；需跟进任务数量
    """
    # 获取AllMessageM表内未完成任务数量
    message = AllMessageM.objects.filter(userId=user_id, status='未完成')
    surplus_task = len(message)

    # # 获取MyMessageM表内今日需沟通任务数量
    # detail = MyMessageM.objects.filter(userId=user_id, expect_time__contains=str_now_time)
    # dialog_count = len(detail)

    # 获取MyMessageM表内今日需跟进任务数量
    message_follow = OrderManager.objects.filter(userId=user_id, status='需跟进')
    follow_task = len(message_follow)

    return surplus_task, follow_task


# 销售简报
def sales_kit(user_id):
    """
    :param user_id: 用户登录id
    :return: 销售机会；订单数量；订单金额；未分配订单数量
    """
    # 获取OrderManager表内userId名下未核实订单
    message_chance = OrderManager.objects.filter(userId=user_id, status='未核实')
    sales_chance = len(message_chance)

    # 获取OrderManager表内userId名下订单数量
    sale = OrderManager.objects.filter(userId=user_id)
    signed_count = len(sale)

    # 获取OrderManager表内userId名下订单金额总值
    amount = OrderManager.objects.filter(userId=user_id).values('prize')
    signed_amount = 0
    for i in amount:
        signed_amount += i['prize']

    # 获取Order表内userId名下assignment为空的订单
    not_assign = Order.objects.filter(userId=user_id, assignment='')
    need_allocated = len(not_assign)

    return sales_chance, signed_count, signed_amount, need_allocated


# 已完成订单
def order_completed(user_id):
    """
    :param user_id: 用户登录id
    :return: 已执行订单个数；执行订单总金额；自主签单比
    """
    # 获取OrderManager表内userId名下已完成订单数量
    order_is_completed = OrderManager.objects.filter(userId=user_id, status='已完成')
    executed_orders = len(order_is_completed)

    # 获取OrderManager表内userId名下已完成订单金额总值
    order_amount = order_is_completed.values('prize')
    executed_order_amount = 0
    for i in order_amount:
        executed_order_amount += i['prize']

    # 占比分母分为两部分
    # 1:订单管理者；2:参与订单任务
    assign = Order.objects.exclude(userId=user_id).values('assignment')
    denominator = len(Order.objects.filter(userId=user_id))
    for i in assign:
        if str(user_id) in i['assignment']:
            denominator += 1

    return executed_orders, executed_order_amount, denominator


# 未完成订单
def order_incomplete(user_id):
    """
    :param user_id: 用户登录id
    :return: 本月未完成订单数；下月未完成订单数
    """
    # 获取OrderManager表内userId名下未完成订单数量
    incomplete_oderId = []  # 未完成的订单Id
    this_month, next_month = 0, 0
    # 获取OrderManager表内userId名下未完成的订单Id
    order_not_complete = OrderManager.objects.filter(userId=user_id, status='未完成').order_by('-orderId').values(
        'orderId')
    for i in order_not_complete:
        incomplete_oderId.append(i['orderId'])
    for i in range(len(incomplete_oderId)):
        # 获取Order表内为orderId订单的marryTime
        order_marryTime = Order.objects.filter(orderId=incomplete_oderId[i]).values('marryTime')
        if order_marryTime[0]['marryTime'].split('-')[0] == str_now_time.split('-')[0]:
            if order_marryTime[0]['marryTime'].split('-')[1] == str_now_time.split('-')[1]:
                this_month += 1
            elif order_marryTime[0]['marryTime'].split('-')[1] == ('0' + str(int(str_now_time.split('-')[1]) + 1)):
                next_month += 1

    return this_month, next_month


# 消息记录
def message_record(order_id):
    """
    :param order_id: 订单id
    :return: 该用户当天任务信息
    """
    # 获取MyMessageM表内orderId名下的数据
    time_message = MyMessageM.objects.filter(orderId=order_id).order_by('expect_time')
    message_time = time_message.values('expect_time')
    details = time_message.values('detail')
    all_status = time_message.values('status')
    create_time = time_message.values('create_time')
    show_detail = {}  # 我的消息字典 expect_time:detail格式
    data_list = list()
    for i in range(len(message_time)):
        data_list.clear()
        data_list.append(details[i]['detail'].split(';'))
        if message_time[i]['expect_time'] < str_now_time:
            MyMessageM.objects.filter(orderId=order_id, expect_time=message_time[i]['expect_time']).update(status='已完成')
            data_list.append('已完成')
        else:
            data_list.append(all_status[i]['status'])
        data_list.append(str(create_time[i]['create_time']).split()[0])
        show_detail[message_time[i]['expect_time']] = data_list.copy()

    return show_detail


# 已完成任务
def task_completed(user_id, expect_time):
    """
    :param user_id: 用户登录id
    :param expect_time: 当前时间
    :return: 已完成任务信息
    """
    completed_detail = []
    completed_detail_orderId = []  # 已完成信息的orderId
    # 获取AllMessageM表内userId名下已完成任务的orderId
    completed_database_order = AllMessageM.objects.filter(userId=user_id, status='已完成').values('orderId')
    for i in completed_database_order:
        completed_detail_orderId.append(i['orderId'])
    for i in range(len(completed_detail_orderId)):
        # 获取Order表内为orderId订单的marryTime
        detail_order_marryTime = Order.objects.filter(orderId=completed_detail_orderId[i]).values(
            'marryTime')
        if detail_order_marryTime[0]['marryTime'].split('-')[0] == expect_time.split('-')[0]:
            if detail_order_marryTime[0]['marryTime'].split('-')[1] == expect_time.split('-')[1]:
                incomplete_database_detail = AllMessageM.objects.filter(
                    orderId=completed_detail_orderId[i]).values(
                    'detail')
                completed_detail.append(incomplete_database_detail[0]['detail'])

    return completed_detail


# 未完成任务
def task_incomplete(user_id, expect_time):
    """
    :param user_id: 用户登录id
    :param expect_time: 当前时间
    :return: 未完成任务信息
    """
    incomplete_detail = []
    incomplete_detail_orderId = []
    # 获取AllMessageM表内userId名下未完成任务的orderId
    incomplete_database_order = AllMessageM.objects.filter(userId=user_id, status='未完成').values('orderId')
    for i in incomplete_database_order:
        incomplete_detail_orderId.append(i['orderId'])
    for i in range(len(incomplete_detail_orderId)):
        # 获取Order表内为orderId订单的marryTime
        detail_order_marryTime = Order.objects.filter(orderId=incomplete_detail_orderId[i]).values(
            'marryTime')
        if detail_order_marryTime[0]['marryTime'].split('-')[0] == expect_time.split('-')[0]:
            if detail_order_marryTime[0]['marryTime'].split('-')[1] == expect_time.split('-')[1]:
                incomplete_database_detail = AllMessageM.objects.filter(
                    orderId=incomplete_detail_orderId[i]).values(
                    'detail')
                incomplete_detail.append(incomplete_database_detail[0]['detail'])

    return incomplete_detail


# 图表数据处理
def chart_data_process(user_id):
    """
    :param user_id: 用户登录id
    :return:1/4/7/10月份订单数量；2/5/8/11月份订单数量；3/6/9/12订单数量；每月利润。
    """
    month_order_count = [0 for _ in range(12)]
    total_profit = [0 for _ in range(12)]
    my_order_id = []
    my_marry_time = []
    my_order = Order.objects.filter(userId=user_id).values('orderId', 'marryTime')
    list_size = len(my_order)
    my_prize = OrderManager.objects.filter(userId=user_id).values('prize')
    for i in range(list_size):
        my_order_id.append(my_order[i]['orderId'])
        if my_order[i]['marryTime'] <= str_now_time:
            format_month = int(my_order[i]['marryTime'].split('-')[1])
            my_marry_time.append(format_month)
            total_profit[format_month - 1] += my_prize[i]['prize']
    for month in range(1, 13):
        month_order_count[month - 1] = my_marry_time.count(month)
    return month_order_count, total_profit


# 分页
def pagination(count, origin_info, page_size, page_step, page_current):
    """
    :param count: 数据总量
    :param origin_info: 原始数据集
    :param page_size: 单页数据量
    :param page_step: 页码步长
    :param page_current: 当前页索引
    :return: 分页信息；分页数据集；分页页码
    """
    page_count_total = math.ceil(count / page_size)  # 总页数
    if page_current>page_count_total:
        page_current=1
    start_index = (page_current - 1) * page_size  # 当前页起始索引
    end_index = page_current * page_size  # 结束索引

    if page_current>page_count_total:
        page_current=page_count_total

    if page_count_total != 0:
        div = mark_safe("<div id='total' class='total'>显示 {} - {} 页  ，共{}页   </div>".format(
            page_current, page_count_total, page_count_total)
        )
    else:
        div = mark_safe("<div id='total' class='total'>显示 {} - {} 页  ，共{}页   </div>".format(
            0, 0, 0)
        )
    # 数量较少
    if page_count_total < 2 * page_step + 1:
        start_page = 1
        end_page = page_count_total + 1
    else:
        # 当前页小于步长
        if page_current <= page_step:
            start_page = 1
            end_page = 6
        elif page_current + page_step >= page_count_total:
            start_page = page_count_total - 4
            end_page = page_count_total + 1
        else:
            start_page = page_current - page_step  # 起始页码
            end_page = page_current + page_step + 1  # 结束页码
    now_info = origin_info[start_index:end_index]  # 从数据库获取订单管理表的信息
    page_list = list()

    # 循环建立页码
    next_page = ''
    for i in range(start_page, end_page):
        if i == page_current:
            li = mark_safe(
                "<li class='page-item active' aria-current='page'><a class='page-link' href=' '>{}</a></li>".format(i))
            if i > 1:
                pre_page = mark_safe(
                    '<li class="page-item"><a class="page-link" href="?page={}">上一页</a></li>'.format(i - 1))
                page_list.insert(0, pre_page)
            else:
                pre_page = mark_safe(
                    '<li class="page-item disabled"><a class="page-link" href="?page={}">上一页</a></li>'.format(i - 1))
                page_list.insert(0, pre_page)
            if i < page_count_total:
                next_page = mark_safe(
                    '<li class="page-item"><a class="page-link" href="?page={}">下一页</a></li>'.format(i + 1))
            else:
                next_page = mark_safe(
                    '<li class="page-item disabled"><a class="page-link" href="?page={}">下一页</a></li>'.format(i + 1))
        else:
            li = mark_safe("<li class='page-item'><a class='page-link' href='?page={}'>{}</a></li>".format(i, i))
        page_list.append(li)
    page_list.append(next_page)

    return div, now_info, page_list


# 分行展示
def divide_rows(items_total_count, items_col, origin_data) -> list:
    """
    对数据进行分行返回
    :param items_total_count: 数据条目总数
    :param items_col: 一行的列数
    :param origin_data: 原始数据集
    :return: 分行后数据集
    """
    row_company = (items_total_count // items_col) + 1
    divide_data = [[] for _ in range(row_company)]
    for i in range(items_total_count):
        divide_data[i // items_col].append(origin_data[i])
    return divide_data


# 删除资源
def delete_resource(dic, model, dir_name):
    point_obj = model.objects.filter(**dic)
    if dir_name != 'caseRes':
        wait_delete_index_img = point_obj.values('img_index')[0]['img_index']
        os.remove('%s/%s' % (settings.MEDIA_ROOT, wait_delete_index_img))
    if dir_name == 'hotelRes':
        wait_delete_ppt = point_obj.values('ppt')[0]['ppt']
        os.remove('%s/%s' % (settings.MEDIA_ROOT, wait_delete_ppt))
        point_obj.delete()
        return
    wait_delete_img = point_obj.values(('img_' + dir_name[0:-3]))[0][('img_' + dir_name[0:-3])].split(' ')
    for i in wait_delete_img:
        os.remove('%s/%s/%s' % (settings.MEDIA_ROOT, dir_name, i))
    wait_delete_video = point_obj.values(('video_' + dir_name[0:-3]))[0][('video_' + dir_name[0:-3])]
    if wait_delete_video:
        os.remove('%s/%s' % (settings.MEDIA_ROOT, wait_delete_video))
    point_obj.delete()


# windows下ppt2pdf
def convert_files_in_win(file_name):
    """
    :param file_name: 文件名称
    :return:
    """
    try:
        pythoncom.CoInitialize()  # 调用多线程
        convert_ppt(file_name)  # 转换ppt
    except Exception as e:
        print(repr(e))


# # linux下ppt2pdf
# def convert_files_in_linux(ppt_file):
#     """
#     :param ppt_file: ppt路径
#     """
#     ppt_file = 'App/static/media/hotelRes/' + ppt_file
#     command = 'unoconv -f pdf %s' % (ppt_file)
#     os.system(command)


# 首页txt文本进行读操作
def index_txt_read():
    """
    :return: 图片信息字典(图片名:图片路径);视频路基;公司背景及简介;公司业内地位
    """
    root_dir = os.getcwd() + '/App/index.txt'
    with open(root_dir, "r", encoding='utf-8') as fo:
        lines = fo.read().splitlines()
        # 读取第一行图片名称
        images_name = (lines[0].split(';'))  # 将列表以空格形式分割开，列表存储
        # 获取第二行图片路径
        images_list = lines[1].split(';')  # 将列表以空格形式分割开，列表存储
        for i in range(len(images_list)):
            images_list[i] = 'media/' + images_list[i]
        # 获取第三行视频路径
        view_url = 'media/' + lines[2]
        # 读取第四行公司背景及简介
        company_info = lines[3]
        # 读取第五行公司业内地位
        company_status = lines[4]
        index_dic = dict(zip(images_name[0:-1], images_list[0:-1]))
    return index_dic, view_url, company_info, company_status


# 首页txt文本进行写操作
def index_txt_write(request):
    # 删除以前的本地图片
    root_dir = os.getcwd() + '/App/index.txt'
    if os.path.getsize(root_dir) != 0:
        with open(root_dir, "r", encoding='utf-8') as fo:
            lines = fo.read().splitlines()
            images_list = [x for x in lines[1].split(';') if x]  # 将列表以空格形式分割开，列表存储
            for obj in images_list:
                os.remove('%s/%s' % (settings.MEDIA_ROOT, obj))
            # 删除以前的视频
            video_pass = lines[2]
            os.remove('%s/%s' % (settings.MEDIA_ROOT, video_pass))

    # 写入文本操作
    with open(root_dir, 'w+', encoding='utf-8') as fo:
        # 存入图片名
        name_string = ''  # 定义一个空的字符串，用于存放图片名
        img_name = request.FILES.getlist('index_img')
        for obj in img_name:
            name_string = name_string + str(obj).split('.')[0] + ';'
        fo.write(name_string.strip())  # 将图片名字符串存入文本
        # 存入图片地址
        url_string = ''
        images = request.FILES.getlist('index_img')  # 获取图片文件
        for num in range(len(images)):
            url_img = 'indexRes/' + str(images[num])  # indexRes/图片
            url_string = url_string + url_img + ';'
        fo.write('\n' + url_string.strip())  # 将图片地址符串存入文本

        # 存入本地图片
        for i in range(len(images)):
            where = '%s/%s/%s' % (settings.MEDIA_ROOT, 'indexRes', img_name[i])
            # 分块保存image
            content = images[i].chunks()
            with open(where, 'wb') as f:
                for j in content:
                    f.write(j)

        # 存入视频地址
        index_video = request.FILES.get('video_index')
        fo.write('\n' + 'indexRes/' + index_video.name)  # 将图片名字符串存入文本

        # 存入本地视频
        where = '%s/%s/%s' % (settings.MEDIA_ROOT, 'indexRes', index_video.name)
        content = index_video.chunks()
        with open(where, 'wb') as f:
            for j in content:
                f.write(j)

        # 存入公司背景及简介
        company_info = request.POST.get('info_index')
        fo.write('\n' + company_info)  # 将图片名字符串存入文本

        # 存入公司业内地位
        company_status = request.POST.get('status_index')
        fo.write('\n' + company_status)  # 将图片名字符串存入文本


# 发送消息内容到邮箱
def send_email(message):
    """
    :param message: 要发送的信息
    """
    # 发送邮件
    send_mail(subject="BUG反馈",
              message="hello",
              from_email=settings.EMAIL_FROM,
              recipient_list=["2659196286@qq.com", "1447240529@qq.com", "948871300@qq.com"],
              html_message=message)
